#include "stdafx.h"

#include <cassert>

#include "Funds.h"

Funds::Funds(double orginalAmount)
:m_orginalAmount(orginalAmount),m_available(orginalAmount),
m_lossAmount(0),m_gainAmount(0),
m_charge(0)
{
}

UINT Funds::GetFreezeCount() const
{
	return m_fundOperateMap.size();
}

bool Funds::HasEnough(double amount)
{
	return m_available >= amount;
}

bool Funds::Freeze(UINT serialNumber, double amount)
{
	if (HasEnough(amount))
	{
		FundOperateMap::iterator iter = m_fundOperateMap.find(serialNumber);
		if (iter != m_fundOperateMap.end())
			return false;
		Serial serial = {0};
		serial.freeze = amount;
		m_fundOperateMap[serialNumber] = serial;
		m_available -= amount;

		return true;
	}
	return false;
}


bool Funds::Unfreeze(UINT serialNumber)
{
	FundOperateMap::iterator iter = m_fundOperateMap.find(serialNumber);
	if (iter == m_fundOperateMap.end())
		return false;

	m_available += iter->second.freeze;
	m_fundOperateMap.erase(iter);

	return true;
}

double Funds::GetAvailable() const
{
	return m_available;
}


double Funds::GetFreezeAmount(UINT serialNumber) const
{
	FundOperateMap::const_iterator iter = m_fundOperateMap.find(serialNumber);
	if (iter == m_fundOperateMap.end())
		return 0.0;

	return iter->second.freeze;
}

void Funds::SetOrginalAmount(double orginalAmount)
{
	m_available = orginalAmount;
	m_orginalAmount = orginalAmount;
	m_fundOperateMap.clear();
	m_gainAmount = 0.00;
	m_charge = 0.00;
	m_lossAmount = 0.00;
}

double Funds::GetOrginalAmount() const
{
	return m_orginalAmount;
}

bool Funds::Open(double amount,double charge)
{
	if (m_available >= amount + charge)
	{
		m_available -= amount;
		m_available -= charge;
		m_charge += charge;
		return true;
	}
	return false;
}

void Funds::Loss(double returnAmount, double charge, double lossAmount)
{
	m_available += returnAmount;
	m_available -= charge;
	m_available -= lossAmount;
	m_lossAmount += lossAmount;
	m_charge += charge;
}

void Funds::Gain(double returnAmount, double charge, double gainAmount)
{
	m_available += returnAmount;
	m_available -= charge;
	m_gainAmount += gainAmount;
	m_charge += charge;
}

void Funds::Offset(double returnAmount, double charge, double profit)
{
	if (profit >= 0)
	{
		Gain(returnAmount,charge,profit);
	}
	else
	{
		Loss(returnAmount,charge,-profit);
	}

}